<?php

/**
 * @name Filters [Match, Get]: Filters for variables, can check for MATCH, or can EXTRACT valid variable
 * @version 0.1, August 28, 2008
 * @copyright &copy; 2008 Novachok, A.
 * @author Snow (Novachok Alexandr) <novachok@gmail.com>
 * @package Filtes [Match, Get]
 *
 */
class meccanoFilters
{
   protected $a_regexp = array(
       'match' => array(
           'HexColor' => '/^#?([\dA-F]{3}){1,2}$/i',
           'Email' => '/(^[\w\.!#$%"*+\/=?`{}|~^-]+)@(([-\w]+\.)+[A-Za-z]{2,})$/',
           'Url' => '/^(https?|ftp):\/\/([.\/_a-z0-9-])+$/i',
           'Integer' => '/^-?\d+$/',
           'Numeric' => '/^-?(\d*\.)?\d+$/',
           'Alpha' => '/^[\w\s-_\.]+$/i',
           'AlphaNum' => '/^[\w\d\s-_\.]+$/i',
           'String' => '/^[-A-Z0-9\.\'"_ ]*$/i',
           'Ip' => '/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}+$/',
           'Bool' => '/^(yes|true|1)+$/i'
       ),
       'get' => array(
           'Integer' => '/\d+/',
           'Numeric' => '/\d+(\.\d+)?/',
           'Alpha' => '/[\w\s-_\.]+/i',
           'String' => '/[-A-Z0-9\.\'"_ ]+/i',
           'Trim' => '/^\s*(.*?)\s*$/'
       )
   );

   protected $ERROR = NULL;

   protected function  __construct()
   {
      $this->ERROR = error::getInstance();
   }

   public function __call($method, $value)
   {
      $trigerError = TRUE;
      $return = FALSE;

      if (strpos($method, 'isValid') === 0)
      {
         # isValid PROCEDURE
         $FilterKey = substr($method, 7);
         if (isset($this->a_regexp['match'][$FilterKey]))
         {
            $trigerError = FALSE;
            $return = (bool) preg_match($this->a_regexp['match'][$FilterKey], current($value));
         }
      } elseif (strpos($method, 'getFirst') === 0)
      {
         # getFirst MATCH
         $FilterKey = substr($method, 8);
         if (isset($this->a_regexp['get'][$FilterKey]))
         {
            $trigerError = FALSE;
            preg_match($this->a_regexp['get'][$FilterKey], current($value), $mathes);
            if (!empty($mathes))
               $return = $mathes[0];
         }
      } elseif (strpos($method, 'getAll'))
      {
         # getAll MATCHES
         $FilterKey = substr($method, 6);
         if (isset($this->a_regexp['get'][$FilterKey]))
         {
            $trigerError = FALSE;
            preg_match_all($this->a_regexp['get'][$FilterKey], current($value), $mathes);
            if (!empty($mathes[0]))
               $return = $mathes[0];
         }
      } elseif (strpos($method, 'filterFor') === 0)
      {
         # filterFor to get from array or variable MATCH value
         $FilterKey = substr($method, 9);
         if (isset($this->a_regexp['match'][$FilterKey]))
         {
            $trigerError = FALSE;
            $value = current($value);

            if (is_array($value))
            {
               $return = FALSE;
               foreach ($value AS $k => $v)
               {
                  if (is_array($v))
                  {
                     $subMethod = 'filterFor' . $FilterKey;
                     $v = $this->$subMethod($v);
                     if ($v !== FALSE)
                        $return[$k] = $v;
                  } else
                  {
                     $subMethod = 'isValid' . $FilterKey;
                     if ($this->$subMethod($v))
                     {
                        $return[$k] = $v;
                     }
                  }
               }

               return $return;
            } else
            {
               $subMethod = 'isValid' . $FilterKey;
               if ($this->$subMethod($value))
               {
                  return $value;
               } else
               {
                  return FALSE;
               }
            }
         }
      }

      if($trigerError == TRUE)
      {
         $this->ERROR->setError(array('message' => 'Call to undefined method ' . get_class($this) . '::' . $method . '()'), 3);
      }

      return $return;
   }

   public function ClearString($str)
   {
      return mysql_real_escape_string(stripslashes($str));
   }

   public function ClearHtml($str, $length = false)
   {
      $str = strip_tags($str);
      $str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
      $str = stripslashes($str);
      $str = trim($str);

      if ($length)
      {
         $str = $this->utf8_substr($str, 0, $length);
      }

      return $str;
   }

   private function utf8_substr($str, $offset, $length = null)
   {
      if (function_exists('mb_substr'))
         return mb_substr($str, $offset, $length, 'utf-8');#(PHP 4 >= 4.0.6, PHP 5)
      if (function_exists('iconv_substr'))
         return iconv_substr($str, $offset, $length, 'utf-8');#(PHP 5)

      preg_match_all('/(?>[\x09\x0A\x0D\x20-\x7E]         # ASCII
                      | [\xC2-\xDF][\x80-\xBF]            # non-overlong 2-byte
                      |  \xE0[\xA0-\xBF][\x80-\xBF]       # excluding overlongs
                      | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
                      |  \xED[\x80-\x9F][\x80-\xBF]       # excluding surrogates
                      |  \xF0[\x90-\xBF][\x80-\xBF]{2}    # planes 1-3
                      | [\xF1-\xF3][\x80-\xBF]{3}         # planes 4-15
                      |  \xF4[\x80-\x8F][\x80-\xBF]{2}    # plane 16
                     )/xs', $str, $m);
      if ($length !== null)
         $a = array_slice($m[0], $offset, $length);
      else
         $a = array_slice($m[0], $offset);

      return implode('', $a);
   }

}


class filters extends meccanoFilters
{
   public function  __construct()
   {
      parent::__construct();
   }

   public function populate_FILES_to_POST()
   {
      // TODO move this method to the Request class
      if(!empty($_FILES) && !empty($_FILES['f']))
      {
         $tmp = array();
         foreach($_FILES['f'] AS $key=>$value)
         {
            foreach($value AS $k=>$v)
            {
               if(is_array($v))
               {
                  foreach($v AS $i=>$vv)
                  {
                     $tmp[$k][$i][$key] = $vv;
                     $tmp[$k][$i]['uploaded'] = TRUE;
                  }
               } else
               {
                  $tmp[$k][$key] = $v;
                  $tmp[$k]['uploaded'] = TRUE;
               }
            }
         }

         global $_POST;
         foreach($tmp AS $key=>$value)
         {
            if(!empty($value['uploaded']) && empty($value['error']))
            {
               $_POST['f'][$key] = $value;
            } else
            {
               foreach($value AS $i=>$v)
               {
                  if(!empty($v['uploaded']) && empty($v['error']))
                  {
                     $_POST['f'][$key][$i] = $v;
                  }
               }
            }
         }
      }
   }
}